package driver;
import core.CalculationException;
import core.DmuList;
import core.GlobalPdmOptimization;
import core.Optimization;
import core.Optimizer;
import core.PdmOptimization;
import facilitator.Bisection;
import facilitator.GlobalSolver;
import facilitator.HeuristikSolver;
import facilitator.Tool;
import facilitator.TransitionExplorer;
import java.io.FileNotFoundException;
import java.io.IOException;
import util.Util;
import gui.ChartForm;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Iron {
    static ArrayList<DataSetListItem> datasets = new ArrayList<DataSetListItem>();
    static double[] weightVector = new double[]{21, 34, 11, 13, 15, 22, 32, 21, 34, 11, 13, 15, 22, 32,21, 34, 11, 13, 15, 22, 32, 21, 34, 11, 13, 15, 22, 32, 21, 34, 11, 13, 15, 22, 32, 21, 34, 11};
	public static void graphic(){
		Util.enableWebStart();
		//new MenuFrame();
        //new MainFrame();
        new ChartForm();
	}
	public static void main(String[] args) {
        try{
            //jumper();
            //DoOne("countries_health_remastered", 5);
            //DoOne("countries_patents_remastered", 12);
            //DoOne("countries_education_remastered", 2);
            Iron.graphic();
        } catch (Exception ex) {
            Logger.getLogger(Iron.class.getName()).log(Level.SEVERE, null, ex);
        }
	}
    private static void jumper() throws FileNotFoundException, CalculationException, IOException, ClassNotFoundException{
            String[] inputSets = new String[]{
                //"countries_general_remastered",
                //"countries_health_remastered",
                "countries_water_remastered",
                "countries_education_remastered",
                //"countries_gdp_remastered",
                //"countries_educationfields_remastered",
                //"countries_patents_remastered",
                //"countries_population_remastered",
                "nme_gdp_remastered",
                "pdm"};
//            for(int i =0; i<inputSets.length; i++){
//                datasets.add(calcDataSet(inputSets[i]));
//            }
//            serialize(datasets, "remastered.txt");
            deserialize("full.txt");
            Util.print(datasets.size());
            printOut(datasets);
            //detail(datasets, 1, 5);
            //detail(datasets, 6, 12);
            //detail(datasets, 3, 2);
    }
    private static void detail(ArrayList<DataSetListItem> datasetlist, int dataset, int dmu) throws CalculationException{
        Util.print(AnalysisHelper.GetObjectHeader());
        //for(DataSetListItem d:datasetlist){
        DataSetListItem d = datasetlist.get(dataset);
        AnalysisHelper helper = new AnalysisHelper(d);
        Util.print(helper.GetObjectToCSVString());
        Util.print(helper.GetExtremeDmuString());

        Util.print("DMU " + dmu);
        Util.print("Alpha;Obj-Heur;Obj-Glob;Objective reached (%);Cnt Glob Optimizers;PD-Heur;PD-Glob;PD reached (%);Eff-Heur;Eff-Glob;Eff reached (%)");
            for(AnalysisItem a: d.dmus.get(dmu).anaList){
                    GlobalPdmOptimization globo = (GlobalPdmOptimization)a.globOptimization;
                    Util.print(a.heurOptimization.getAlpha() + ";"
                            + a.heurOptimization.getOptimizationObjective()+ ";"
                            + a.globOptimization.getOptimizationObjective() + ";"
                            + (a.heurOptimization.getOptimizationObjective()/a.globOptimization.getOptimizationObjective()*100) + ";"
                            + globo.optimizers.size() + ";"
                            + a.heurOptimization.getProfileDistance() + ";"
                            + a.globOptimization.getProfileDistance() + ";"
                            + (a.heurOptimization.getProfileDistance()/a.globOptimization.getProfileDistance()*100) + ";"
                            + a.heurOptimization.getEfficiency() + ";"
                            + a.globOptimization.getEfficiency() + ";"
                            + (a.heurOptimization.getEfficiency()/a.globOptimization.getEfficiency()*100));
                }
//                AnalysisItem a = d.dmus.get(dmu).anaList.get(0);
//                    GlobalPdmOptimization globo = (GlobalPdmOptimization)a.globOptimization;
//                    Util.print(a.heurOptimization.getAlpha() + ";"
//                            + a.heurOptimization.getOptimizationObjective()+ ";"
//                            + a.globOptimization.getOptimizationObjective() + ";"
//                            + (a.heurOptimization.getOptimizationObjective()/a.globOptimization.getOptimizationObjective()*100) + ";"
//                            + globo.optimizers.size() + ";"
//                            + a.heurOptimization.getProfileDistance() + ";"
//                            + a.globOptimization.getProfileDistance() + ";"
//                            + (a.heurOptimization.getProfileDistance()/a.globOptimization.getProfileDistance()*100) + ";"
//                            + a.heurOptimization.getEfficiency() + ";"
//                            + a.globOptimization.getEfficiency() + ";"
//                            + (a.heurOptimization.getEfficiency()/a.globOptimization.getEfficiency()*100));
//                    for(PdmOptimization op:globo.optimizers){
//                        Util.print(Arrays.toString(op.getOptimizationDirections()));
//                    }
                
        
    }
    private static void DoOne(String filename, int dmu) throws NumberFormatException, CalculationException, IOException{
        DmuList dmus = Util.LoadFile("input\\" + filename + ".csv");
        double[] urmWeights = getUrmWeights(dmus.outputSize);
        Util.print("URM vector: " + Arrays.toString(urmWeights));

    /*    GlobalSolver globSolv = new GlobalSolver(dmus, dmu, urmWeights);
        GlobalPdmOptimization globOpt = (GlobalPdmOptimization)globSolv.getOptimization(0);
         Util.print("done " + globOpt.optimizers.size());
        for(PdmOptimization op:globOpt.optimizers){
                        Util.print(Arrays.toString(op.getOptimizationDirections()));
                    }*/


        double alpha = 0d;//103.80346052662200d;
        //Bisection_1 heur = new Bisection_1(dmus, dmu, urmWeights, Bisection_1.SolverModell.Heuristik, 0.1E-8);
        //List<PdmOptimization> heurOpts = diaHelper(heur.getTransitions());
//        Optimization deaOpt = new Optimization(dmus, dmu);
//        Optimizer.calculateDea(deaOpt);
//        Util.print("----------DEA-----------");
//        Util.print(deaOpt.getOptimizationObjective() + ";"
//                + deaOpt.getEfficiency());
//        Util.print(Arrays.toString(deaOpt.getOptimizationOutputWeights()));
//
//        Util.print("----------PDM-----------");
//        PdmOptimization heur = new PdmOptimization(dmus, dmu, alpha, urmWeights, deaOpt);
//        Optimizer.calculatePdm(heur);
//        Util.print("URM relative: " + Arrays.toString(heur.getRelUrmWeights()));
//        Util.print("Alpha: " + alpha);
//       Util.print(heur.getOptimizationObjective() + ";"
//                + heur.getEfficiency() + ";"
//                + heur.getProfileDistance() + ";");
//       Util.print(Arrays.toString(heur.getOptimizationOutputWeights()));
//       Util.print(Arrays.toString(heur.getOptimizationDirections()));
//       Util.print("_______________");
//
//       GlobalSolver globSolv = new GlobalSolver(dmus, dmu, urmWeights);
//       GlobalPdmOptimization globOpt = (GlobalPdmOptimization)globSolv.getOptimization(alpha);
//       Util.print("Global: " + (globOpt.optimizers.size()-1));
//       //for(PdmOptimization g : globOpt.optimizers){
//           PdmOptimization g = globOpt.optimizers.get(0);
//            Util.print(g.getOptimizationObjective() + ";"
//                + g.getEfficiency() + ";"
//                + g.getProfileDistance() + ";");
//            Util.print(Arrays.toString(g.getOptimizationOutputWeights()));
//            Util.print(Arrays.toString(g.getRelOptimizationWeights()));
//            Util.print(Arrays.toString(g.getOptimizationDirections()));
//            Util.print("_______________");
       //}


      

       Util.print("Alpha;Obj-Heur;Obj-Glob;Objective reached (%);Cnt Glob Optimizers;Cnt different Optimizers;PD-Heur;PD-Glob;PD reached (%);Eff-Heur;Eff-Glob;Eff reached (%)");
        //List<PdmOptimization> heurOpts = heur.getTransitions();
        //Util.print("Found transitions: " + heurOpts.size());
        GlobalSolver globSolv = new GlobalSolver(dmus, dmu, urmWeights);
//        for (PdmOptimization a : heurOpts){
//            GlobalPdmOptimization globo = (GlobalPdmOptimization)globSolv.getOptimization(a.getAlpha());
//                    Util.print(a.getAlpha() + ";"
//                            + a.getOptimizationObjective()+ ";"
//                            + globo.getOptimizationObjective() + ";"
//                            + (a.getOptimizationObjective()/globo.getOptimizationObjective()*100) + ";"
//                            + globo.optimizers.size() + ";"
//                            + Tool.getDifferentOptimizers(globo.optimizers) + ";"
//                            + a.getProfileDistance() + ";"
//                            + globo.getProfileDistance() + ";"
//                            + (a.getProfileDistance()/globo.getProfileDistance()*100) + ";"
//                            + a.getEfficiency() + ";"
//                            + globo.getEfficiency() + ";"
//                            + (a.getEfficiency()/globo.getEfficiency()*100));
//       }
        alpha = 0.671557382680475;
        HeuristikSolver heurSolv = new HeuristikSolver(dmus, dmu, urmWeights);
        GlobalPdmOptimization globo = (GlobalPdmOptimization)globSolv.getOptimization(alpha);
        PdmOptimization heurOpt = heurSolv.getOptimization(alpha);

                    Util.print("Diffs: " + Tool.getDifferentOptimizers(globo.optimizers));

                    /*for(PdmOptimization op:globo.optimizers){
                        Util.print(op.getOptimizationObjective() + " -- " + op.getEfficiency());
                    }*/
                    for(PdmOptimization op:globo.optimizers){
                        Util.print(Arrays.toString(op.getRelOptimizationWeights()));
                    }
                    //Util.print(Arrays.toString(heurOpt.getRelOptimizationWeights()));
                    //Util.print(Arrays.toString(globo.getRelUrmWeights()));
                    //Util.print(globo.optimizers.size());
    }
    private static List<PdmOptimization> diaHelper(List<PdmOptimization> list) throws CalculationException{
        for(int i = 1; i< list.size()-1;i++){
            if(list.get(i).getAlpha() == list.get(i-1).getAlpha()){
                list.get(i).setOptimizationObjective(list.get(i+1).getOptimizationObjective());
                list.get(i).setProfileDistance(list.get(i+1).getProfileDistance());
            }
        }
        return list;
    }
    private static void deserialize(String filename) throws FileNotFoundException, IOException, ClassNotFoundException {
        Util.print("Starting deserialization " + Util.getTimeStamp());
        datasets = null;
		FileInputStream fis = null;
		ObjectInputStream in = null;
		fis = new FileInputStream(filename);
		in = new ObjectInputStream(fis);
		datasets = (ArrayList<DataSetListItem>) in.readObject();
		in.close();
        Util.print("Finished deserialization " + Util.getTimeStamp());
    }
    private static void serialize(ArrayList<DataSetListItem> datasetlist, String filename){

        FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = new FileOutputStream(filename);
			out = new ObjectOutputStream(fos);
			out.writeObject(datasetlist);
			out.close();
			System.out.println("Object Persisted");
		} catch (IOException ex) {
			ex.printStackTrace();
		}

    }
    private static void printOut(ArrayList<DataSetListItem> datasetlist) throws CalculationException{
        Util.print(AnalysisHelper.GetObjectHeader());
        for(DataSetListItem d:datasetlist){
//            if(d.dmus.size() == 29){
            Util.print("DATASET: " + d.datasetname);
            //AnalysisHelper helper = new AnalysisHelper(d);
            //Util.print(helper.GetObjectToCSVString());
            //Util.print(helper.GetExtremeDmuString());
            for(DmuListItem dmu : d.dmus){
                Util.print("\tDMU: " + dmu.dmu);
                //Util.print("Alpha;HeurObj;GlobObj;HeurDist;GlobDist");
                for(AnalysisItem a:dmu.anaList){
                    int diffs = Tool.getDifferentOptimizers(((GlobalPdmOptimization)a.globOptimization).optimizers);
                    if(diffs > 1){
                        Util.print(a.globOptimization.getAlpha() + ";" + diffs);
                    }
                    //Util.print(a.heurOptimization.getAlpha() + ";" + a.heurOptimization.getOptimizationObjective()+ ";" + a.globOptimization.getOptimizationObjective() + ";" + a.heurOptimization.getProfileDistance() +";" + a.globOptimization.getProfileDistance());
                }
            }
//            }

        }

    }
    private static double[] getUrmWeights(int cnt){
            double[] urmWeights = new double[cnt];

            for(int i = 0; i< cnt; i++){
                urmWeights[i] = weightVector[i];
            }

            return urmWeights;
    }
    public static DataSetListItem calcDataSet(String filename) throws NumberFormatException, CalculationException, IOException{
        Util.print("CalcDataSet " + filename + " - " + Util.getTimeStamp());
        DataSetListItem curr = new DataSetListItem(filename);
        DmuList dmus = Util.LoadFile("input\\" + filename + ".csv");
        double[] urmWeights = getUrmWeights(dmus.outputSize);
        for(int i=0;i<dmus.size();i++){
            Util.print("\tDMU " + i + " - " + Util.getTimeStamp());
            DmuListItem dmu = new DmuListItem(i);
            Bisection heur = new Bisection(dmus, i, urmWeights, Bisection.SolverModell.Heuristik, 0.1E-5);
            List<PdmOptimization> heurOpts = heur.getTransitions();
            Util.print("\tFOUND TRANSITIONS: " + heurOpts.size());
            Util.print("\t\tSTEP 1 - " + Util.getTimeStamp());
            GlobalSolver globSolv = new GlobalSolver(dmus, i, urmWeights);
            int x=0;
            for (PdmOptimization heurOpt : heurOpts){
                dmu.anaList.add(new AnalysisItem(heurOpt, globSolv.getOptimization(heurOpt.getAlpha())));
                Util.print("\t\tSTEP 2." + ++x + " - " + Util.getTimeStamp());
            }
            curr.dmus.add(dmu);
        }
        return curr;
    }

  
	
}
